{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1.import libs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"A script for data collection on Quafu platform.\"\"\"\n",
    "import sys\n",
    "import os\n",
    "sys.path.append(os.path.abspath(os.path.join(os.getcwd(), '..')))\n",
    "\n",
    "from utils.get_data import ShotTestReceiver, CircuitReceiver\n",
    "from qiskit import QuantumCircuit, ClassicalRegister\n",
    "from qiskit.qasm2 import dumps, loads  # Use this for QASM conversion\n",
    "import itertools\n",
    "import random"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2.define some helpful functions\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "def create_test_circuit(qubit_indices: list, circuit_type: str, mapping: dict = None,\n",
    "                         qed_pilocy: str='0011', xtest_gate_num: int=0, number_of_gates: int=0,\n",
    "                         measure_all: bool=True) -> str:\n",
    "    \n",
    "    \"\"\"Create a test circuit with Hadamard gates and CNOT gates.\n",
    "    \n",
    "    This function creates a quantum circuit that applies Hadamard gates and CNOT gates\n",
    "    to specified physical qubits and converts it to QASM format.\n",
    "    \n",
    "    Args:\n",
    "        qubit_indices: List of physical qubit indices to map the logical qubits to\n",
    "        circuit_type: str, 'H' or 'random_1'\n",
    "        mapping: dict, the mapping of the qubits to the logical qubits, e.g. {37: [44]}, means the state of qubit 37 is copyed to the qubit 44.\n",
    "        xtest_gate_num: int, number of X test gates to apply to mapping qubit\n",
    "        qed_pilocy: str, the qed pilocy to use, e.g. '0011', '0110'\n",
    "        number_of_gates: int, number of gates to apply to each qubit\n",
    "\n",
    "    Returns:\n",
    "        str: QASM representation of the circuit\n",
    "    \"\"\"\n",
    "    import math\n",
    "\n",
    "    # Create circuit with enough qubits for the physical indices\n",
    "    max_qubit_idx = max(qubit_indices) + 1\n",
    "    circuit = QuantumCircuit(max_qubit_idx, len(qubit_indices))\n",
    "\n",
    "    if circuit_type == 'None':\n",
    "        if mapping:\n",
    "            for qubit, map_qubits in mapping.items():\n",
    "                for map_qubit in map_qubits:\n",
    "                    circuit.cx(qubit, map_qubit)\n",
    "                    if qed_pilocy == '0110':\n",
    "                        circuit.x(map_qubit)\n",
    "                    \n",
    "                        for _ in range(xtest_gate_num):\n",
    "                            circuit.x(map_qubit)\n",
    "\n",
    "    elif circuit_type == 'H':\n",
    "        # Add hadamard gates using physical qubit indices directly\n",
    "        circuit.h(qubit_indices[0])  # Single Hadamard gate\n",
    "        if mapping:\n",
    "            for qubit, map_qubits in mapping.items():\n",
    "                for map_qubit in map_qubits:\n",
    "                    circuit.cx(qubit, map_qubit)\n",
    "                    if qed_pilocy == '0110':\n",
    "                        circuit.x(map_qubit)\n",
    "                    \n",
    "                        for _ in range(xtest_gate_num):\n",
    "                            circuit.x(map_qubit)\n",
    "        else:\n",
    "            circuit.h(qubit_indices[0])\n",
    "    elif circuit_type == 'random':\n",
    "        # Add 1-qubit gates randomly\n",
    "        # Add random single-qubit gates\n",
    "        for qubit, map_qubits in mapping.items():            \n",
    "            # Choose a random number of gates to apply to this qubit (1-3)\n",
    "            num_gates_per_qubit = number_of_gates\n",
    "            \n",
    "            for _ in range(num_gates_per_qubit):\n",
    "                # Select a random gate from the single-qubit gate set\n",
    "                gate_type = random.choice(['h', 'x', 'y', 'z', 'rx', 'ry', 'rz'])\n",
    "                \n",
    "                # Apply the selected gate\n",
    "                if gate_type == 'h':\n",
    "                    circuit.h(qubit)\n",
    "                elif gate_type == 'x':\n",
    "                    circuit.x(qubit)\n",
    "                elif gate_type == 'y':\n",
    "                    circuit.y(qubit)\n",
    "                elif gate_type == 'z':\n",
    "                    circuit.z(qubit)\n",
    "                elif gate_type == 'rx':\n",
    "                    # Random angle between 0 and 2π using math.pi for accuracy\n",
    "                    theta = random.uniform(-1*math.pi+1e-5, math.pi-1e-5)\n",
    "                    circuit.rx(theta, qubit)\n",
    "                elif gate_type == 'ry':\n",
    "                    theta = random.uniform(-1*math.pi+1e-5, math.pi-1e-5)\n",
    "                    circuit.ry(theta, qubit)\n",
    "                elif gate_type == 'rz':\n",
    "                    theta = random.uniform(-1*math.pi+1e-5, math.pi-1e-5)\n",
    "                    circuit.rz(theta, qubit)\n",
    "\n",
    "            for map_qubit in map_qubits:\n",
    "                circuit.cx(qubit, map_qubit)\n",
    "                if qed_pilocy == '0110':\n",
    "                    circuit.x(map_qubit)\n",
    "                    for _ in range(xtest_gate_num):\n",
    "                        circuit.x(map_qubit)\n",
    "        if mapping is None:\n",
    "            qubit = qubit_indices[0]\n",
    "            # Choose a random number of gates to apply to this qubit (1-3)\n",
    "            num_gates_per_qubit = number_of_gates\n",
    "            \n",
    "            for _ in range(num_gates_per_qubit):\n",
    "                # Select a random gate from the single-qubit gate set\n",
    "                gate_type = random.choice(['h', 'x', 'y', 'z', 'rx', 'ry', 'rz'])\n",
    "                \n",
    "                # Apply the selected gate\n",
    "                if gate_type == 'h':\n",
    "                    circuit.h(qubit)\n",
    "                elif gate_type == 'x':\n",
    "                    circuit.x(qubit)\n",
    "                elif gate_type == 'y':\n",
    "                    circuit.y(qubit)\n",
    "                elif gate_type == 'z':\n",
    "                    circuit.z(qubit)\n",
    "                elif gate_type == 'rx':\n",
    "                    # Random angle between 0 and 2π using math.pi for accuracy\n",
    "                    theta = random.uniform(-1*math.pi+1e-5, math.pi-1e-5)\n",
    "                    circuit.rx(theta, qubit)\n",
    "                elif gate_type == 'ry':\n",
    "                    theta = random.uniform(-1*math.pi+1e-5, math.pi-1e-5)\n",
    "                    circuit.ry(theta, qubit)\n",
    "                elif gate_type == 'rz':\n",
    "                    theta = random.uniform(-1*math.pi+1e-5, math.pi-1e-5)\n",
    "                    circuit.rz(theta, qubit)\n",
    "            \n",
    "\n",
    "\n",
    "    # Add measurements for all qubits\n",
    "    if measure_all:\n",
    "        for i, qubit in enumerate(qubit_indices):\n",
    "            circuit.measure(qubit, i)\n",
    "    \n",
    "    return dumps(circuit)\n",
    "\n",
    "def create_readout_benchmark_circuit(qubit_indices: list, measure_all: bool=True) -> list[str]:\n",
    "    \"\"\"Create benchmark circuits for readout error characterization.\n",
    "    \n",
    "    This function generates circuits that prepare all possible computational basis\n",
    "    states for the specified qubits to characterize readout errors.\n",
    "    \n",
    "    Args:\n",
    "        qubit_indices: List of physical qubit indices to benchmark\n",
    "        measure_all: bool, whether to measure all qubits\n",
    "        \n",
    "    Returns:\n",
    "        list[str]: List of QASM strings for all state preparation combinations\n",
    "    \"\"\"\n",
    "    n_qubits = len(qubit_indices)\n",
    "    benchmark_n = len(qubit_indices)\n",
    "    preparations = list(itertools.product([0,1], repeat=benchmark_n))\n",
    "    circuits = []\n",
    "    \n",
    "    for prep in preparations:\n",
    "        max_qubit_idx = max(qubit_indices) + 1\n",
    "        circuit = QuantumCircuit(max_qubit_idx, n_qubits)\n",
    "        \n",
    "        # Prepare basis states\n",
    "        for qubit, state in zip(qubit_indices, prep):\n",
    "            if state == 1:\n",
    "                circuit.x(qubit)\n",
    "\n",
    "        # Add measurements\n",
    "        if measure_all:\n",
    "            for i, qubit in enumerate(qubit_indices):\n",
    "                circuit.measure(qubit, i)\n",
    "            \n",
    "        circuits.append(dumps(circuit))\n",
    "        \n",
    "    return circuits"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3.get data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Execution date: 2025-04-09\n"
     ]
    }
   ],
   "source": [
    "# Get the current date when this code is executed\n",
    "from datetime import datetime\n",
    "date = datetime.now().strftime(\"%Y-%m-%d\")\n",
    "print(f\"Execution date: {date}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3.1 receive data of shot test  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 00 and 11"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "qubit_indices = [44, 50]    # readout error rate 1.38 1.14\n",
    "# qubit_indices = [20, 26]    # readout error rate 1.12 1.26\n",
    "# qubit_indices = [2, 9]    # readout error rate 1.67 1.6\n",
    "# qubit_indices = [23, 29] # readout error rate 2.23 2.39\n",
    "\n",
    "circuit_type = 'H'\n",
    "number_of_gates = 10\n",
    "shot_range = [5*int(1e3), 7*int(1e3), int(1e4)] #, int(1e5)]\n",
    "# login_key = 'kCO7NfSBK79mgrEV+zE39oeGLBVrY+JUBQ07lp22NL0='\n",
    "login_key = 'gtKfDJ1O/qUncccbTQ6m1wYyNygTb/NW/T+y8DAAwvI='\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "ename": "IndexError",
     "evalue": "list index out of range",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mIndexError\u001b[0m                                Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[51], line 19\u001b[0m\n\u001b[1;32m      4\u001b[0m shot_test_platform_config \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m      5\u001b[0m     \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mplatform\u001b[39m\u001b[38;5;124m'\u001b[39m: \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtianyan\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m      6\u001b[0m     \u001b[38;5;66;03m# 'login_key': '8N8TOqEEhrGznQPEoguaiDF6NEFWjSdL2UlZwDV9Ks8.Qf3YjMyQTNyQzNxojIwhXZiwiM4kDN6ICZpJye.9JiN1IzUIJiOicGbhJCLiQ1VKJiOiAXe0Jye',\u001b[39;00m\n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m     13\u001b[0m     \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mexp_name\u001b[39m\u001b[38;5;124m'\u001b[39m: \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mlen\u001b[39m(qubit_indices)\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m-qubit_\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mcircuit_type\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m_\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mqed_pilocy\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m_\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mxtest_gate_num\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m_qubits_\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m-\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;241m.\u001b[39mjoin(\u001b[38;5;28mmap\u001b[39m(\u001b[38;5;28mstr\u001b[39m,\u001b[38;5;250m \u001b[39mqubit_indices))\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m'\u001b[39m  \u001b[38;5;66;03m# Include number of qubits, circuit type and qubit indices\u001b[39;00m\n\u001b[1;32m     14\u001b[0m }\n\u001b[1;32m     17\u001b[0m test_circuits_receiver \u001b[38;5;241m=\u001b[39m ShotTestReceiver(shot_test_platform_config, shot_range\u001b[38;5;241m=\u001b[39mshot_range, circuit_nums\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m1\u001b[39m)\n\u001b[1;32m     18\u001b[0m test_circuits_receiver\u001b[38;5;241m.\u001b[39msubmit_experiment(create_test_circuit(qubit_indices\u001b[38;5;241m=\u001b[39mqubit_indices, circuit_type\u001b[38;5;241m=\u001b[39mcircuit_type,\n\u001b[0;32m---> 19\u001b[0m                                           mapping\u001b[38;5;241m=\u001b[39m{qubit_indices[\u001b[38;5;241m0\u001b[39m]: [\u001b[43mqubit_indices\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m]\u001b[49m]}, qed_pilocy\u001b[38;5;241m=\u001b[39mqed_pilocy, xtest_gate_num\u001b[38;5;241m=\u001b[39mxtest_gate_num, \n\u001b[1;32m     20\u001b[0m                                           number_of_gates\u001b[38;5;241m=\u001b[39mnumber_of_gates))\n",
      "\u001b[0;31mIndexError\u001b[0m: list index out of range"
     ]
    }
   ],
   "source": [
    "qed_pilocy = '0011'\n",
    "xtest_gate_num = 0\n",
    "\n",
    "shot_test_platform_config = {\n",
    "    'platform': 'tianyan',\n",
    "    'login_key': login_key,\n",
    "    # 'machine_name': 'tianyan_tnn',\n",
    "    'machine_name': 'tianyan176-2',\n",
    "    'num_qubits': len(qubit_indices),\n",
    "    'exp_name': f'{len(qubit_indices)}-qubit_{circuit_type}_{qed_pilocy}_{xtest_gate_num}_qubits_{\"-\".join(map(str, qubit_indices))}'  # Include number of qubits, circuit type and qubit indices\n",
    "}\n",
    "\n",
    "\n",
    "test_circuits_receiver = ShotTestReceiver(shot_test_platform_config, shot_range=shot_range, circuit_nums=1)\n",
    "test_circuits_receiver.submit_experiment(create_test_circuit(qubit_indices=qubit_indices, circuit_type=circuit_type,\n",
    "                                          mapping={qubit_indices[0]: [qubit_indices[1]]}, qed_pilocy=qed_pilocy, xtest_gate_num=xtest_gate_num, \n",
    "                                          number_of_gates=number_of_gates))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_circuits_receiver.receive_results()\n",
    "test_circuits_receiver.save_results(f'../results/{date}/test_circuits/')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 01 and 01, x=0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Job submission completed.\n",
      "Job submission completed.\n",
      "Job submission completed.\n"
     ]
    }
   ],
   "source": [
    "qed_pilocy = '0110'\n",
    "xtest_gate_num = 0\n",
    "\n",
    "shot_test_platform_config = {\n",
    "    'platform': 'tianyan',\n",
    "    'login_key': login_key,\n",
    "    # 'machine_name': 'tianyan_tnn',\n",
    "    'machine_name': 'tianyan176-2',\n",
    "    'num_qubits': len(qubit_indices),\n",
    "    'exp_name': f'{len(qubit_indices)}-qubit_{circuit_type}_{qed_pilocy}_{xtest_gate_num}_qubits_{\"-\".join(map(str, qubit_indices))}'  # Include number of qubits, circuit type and qubit indices\n",
    "}\n",
    "\n",
    "\n",
    "test_circuits_receiver = ShotTestReceiver(shot_test_platform_config, shot_range=shot_range, circuit_nums=1)\n",
    "test_circuits_receiver.submit_experiment(create_test_circuit(qubit_indices=qubit_indices, circuit_type=circuit_type,\n",
    "                                          mapping={qubit_indices[0]: [qubit_indices[1]]}, qed_pilocy=qed_pilocy, xtest_gate_num=xtest_gate_num, \n",
    "                                          number_of_gates=number_of_gates))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_circuits_receiver.receive_results()\n",
    "test_circuits_receiver.save_results(f'../results/{date}/test_circuits/')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 01 and 01, x=2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Job submission completed.\n",
      "Job submission completed.\n",
      "Job submission completed.\n"
     ]
    }
   ],
   "source": [
    "qed_pilocy = '0110'\n",
    "xtest_gate_num = 2\n",
    "\n",
    "shot_test_platform_config = {\n",
    "    'platform': 'tianyan',\n",
    "    'login_key': login_key,\n",
    "    # 'machine_name': 'tianyan_tnn',\n",
    "    'machine_name': 'tianyan176-2',\n",
    "    'num_qubits': len(qubit_indices),\n",
    "    'exp_name': f'{len(qubit_indices)}-qubit_{circuit_type}_{qed_pilocy}_{xtest_gate_num}_qubits_{\"-\".join(map(str, qubit_indices))}'  # Include number of qubits, circuit type and qubit indices\n",
    "}\n",
    "\n",
    "\n",
    "test_circuits_receiver = ShotTestReceiver(shot_test_platform_config, shot_range=shot_range, circuit_nums=1)\n",
    "test_circuits_receiver.submit_experiment(create_test_circuit(qubit_indices=qubit_indices, circuit_type=circuit_type,\n",
    "                                          mapping={qubit_indices[0]: [qubit_indices[1]]}, qed_pilocy=qed_pilocy, xtest_gate_num=xtest_gate_num, \n",
    "                                          number_of_gates=number_of_gates))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_circuits_receiver.receive_results()\n",
    "test_circuits_receiver.save_results(f'../results/{date}/test_circuits/')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3.4 origin"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "s_qubit_indices = [qubit_indices[0]]\n",
    "qed_pilocy = '01'\n",
    "xtest_gate_num = 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Job submission completed.\n",
      "Job submission completed.\n",
      "Job submission completed.\n"
     ]
    }
   ],
   "source": [
    "number_of_gates = 10\n",
    "\n",
    "shot_test_platform_config = {\n",
    "    'platform': 'tianyan',\n",
    "    'login_key': login_key,\n",
    "    # 'machine_name': 'tianyan_tnn',\n",
    "    'machine_name': 'tianyan176-2',\n",
    "    'num_qubits': len(s_qubit_indices),\n",
    "    'exp_name': f'{len(s_qubit_indices)}-qubit_{circuit_type}_{qed_pilocy}_{xtest_gate_num}_qubits_{\"-\".join(map(str, s_qubit_indices))}'  # Include number of qubits, circuit type and qubit indices\n",
    "}\n",
    "\n",
    "\n",
    "test_circuits_receiver = ShotTestReceiver(shot_test_platform_config, shot_range=shot_range, circuit_nums=1)\n",
    "test_circuits_receiver.submit_experiment(create_test_circuit(qubit_indices=s_qubit_indices, circuit_type=circuit_type, \n",
    "                                          number_of_gates=number_of_gates))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_circuits_receiver.receive_results()\n",
    "test_circuits_receiver.save_results(f'../results/{date}/test_circuits/')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.16"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
